import { ecs } from "./ECS";
import { ECSEntity } from "./ECSEntity";
import { ECSGroup } from "./ECSGroup";
import { ECSModel } from "./ECSModel";

/**
 * ECS 组合系统基类（优化版）
 * 
 * 继承此类实现具体业务逻辑
 * 
 * 生命周期钩子（按调用顺序）：
 * 1. init() - 系统初始化（仅一次）
 * 2. entityRemove(entity) - 实体移除时
 * 3. beforeExecute(dt) - 执行前钩子（每帧，在遍历实体之前）
 * 4. entityEnter(entity) - 实体进入时
 * 5. firstUpdate(entity) - 实体首次更新（仅一次）
 * 6. update(entity) - 实体更新（每帧）
 * 7. afterExecute(dt) - 执行后钩子（每帧，在遍历实体之后）
 * 8. onDestroy() - 系统销毁（仅一次）
 * 
 * 优化要点：
 * 1. 使用 forEach 代替 for-of
 * 2. 优化方法绑定策略
 * 3. 减少属性访问次数
 * 4. 提前退出优化
 * 
 * @example
 * ```typescript
 * @ecs.register('Physics')
 * export class PhysicsSystem extends ecs.ComblockSystem implements ecs.ISystemBeforeExecute, ecs.ISystemUpdate, ecs.ISystemAfterExecute {
 *     filter() { return ecs.allOf(PhysicsBodyComp); }
 *     
 *     // 批量操作：开始物理模拟
 *     beforeExecute(dt: number) {
 *         this.physics.startSimulation();
 *     }
 *     
 *     // 处理每个实体
 *     update(entity: Entity) {
 *         this.physics.addBody(entity);
 *     }
 *     
 *     // 批量操作：结束物理模拟
 *     afterExecute(dt: number) {
 *         this.physics.step(dt);
 *     }
 * }
 * ```
 */
export abstract class ECSComblockSystem<E extends ECSEntity = ECSEntity> {
    static s: boolean = true;

    /** 实体组 */
    protected readonly group: ECSGroup<E>;
    
    /** 帧时间差（秒） */
    protected dt: number = 0;

    /** 新进入的实体 */
    private enteredEntities: Map<number, E> = null!;
    
    /** 移除的实体 */
    private removedEntities: Map<number, E> = null!;

    /** 是否有 entityEnter 方法 */
    private readonly hasEntityEnter: boolean = false;
    
    /** 是否有 entityRemove 方法 */
    private readonly hasEntityRemove: boolean = false;
    
    /** 是否有 update 方法 */
    private readonly hasUpdate: boolean = false;

    /** 是否有 beforeExecute 方法 */
    private readonly hasBeforeExecute: boolean = false;

    /** 是否有 afterExecute 方法 */
    private readonly hasAfterExecute: boolean = false;

    /** 临时执行函数（用于 firstUpdate） */
    private tmpExecute: ((dt: number) => void) | null = null;
    
    /** 执行函数（动态绑定） */
    private execute!: (dt: number) => void;

    /**
     * 构造函数
     * 
     * 优化：
     * 1. 缓存原型对象
     * 2. 使用 in 操作符代替 hasOwnProperty
     * 3. 简化执行函数绑定逻辑
     */
    constructor() {
        // 优化：缓存原型对象
        const prototype = Object.getPrototypeOf(this);
        
        // 优化：检查方法是否存在（使用 in 操作符更快）
        const hasEntityEnter = 'entityEnter' in prototype && typeof prototype.entityEnter === 'function';
        const hasEntityRemove = 'entityRemove' in prototype && typeof prototype.entityRemove === 'function';
        const hasFirstUpdate = 'firstUpdate' in prototype && typeof prototype.firstUpdate === 'function';
        const hasUpdate = 'update' in prototype && typeof prototype.update === 'function';
        const hasBeforeExecute = 'beforeExecute' in prototype && typeof prototype.beforeExecute === 'function';
        const hasAfterExecute = 'afterExecute' in prototype && typeof prototype.afterExecute === 'function';

        // @ts-ignore - 设置只读属性
        this.hasEntityEnter = hasEntityEnter;
        // @ts-ignore
        this.hasEntityRemove = hasEntityRemove;
        // @ts-ignore
        this.hasUpdate = hasUpdate;
        // @ts-ignore
        this.hasBeforeExecute = hasBeforeExecute;
        // @ts-ignore
        this.hasAfterExecute = hasAfterExecute;

        // 创建 Group
        // @ts-ignore
        this.group = ECSModel.createGroup(this.filter());

        // 绑定执行函数
        if (hasEntityEnter || hasEntityRemove) {
            this.enteredEntities = new Map<number, E>();
            this.removedEntities = new Map<number, E>();
            this.execute = this.execute1;
            this.group.watchEntityEnterAndRemove(this.enteredEntities, this.removedEntities);
        } else {
            this.execute = this.execute0;
        }

        // 处理 firstUpdate
        if (hasFirstUpdate) {
            this.tmpExecute = this.execute;
            this.execute = this.updateOnce;
        }
    }

    /**
     * 系统初始化
     * 
     * 子类可以重写此方法进行初始化操作
     */
    init(): void {
        // 子类实现
    }

    /**
     * 系统销毁
     * 
     * 子类可以重写此方法进行清理操作
     */
    onDestroy(): void {
        // 子类实现
    }

    /**
     * 检查是否存在实体
     * 
     * 优化：使用 isEmpty getter
     * 
     * @returns true 表示存在实体
     */
    hasEntity(): boolean {
        return !this.group.isEmpty;
    }
    
    /**
     * 获取实体数量
     */
    get entityCount(): number {
        return this.group.count;
    }

    /**
     * 首次更新（执行一次）
     * 
     * 先执行 entityEnter，再执行 firstUpdate，最后切换到正常执行
     * 
     * 优化：使用 forEach 代替 for-of
     * 
     * @param dt 帧时间差
     */
    private updateOnce(dt: number): void {
        // 优化：提前退出
        if (this.group.isEmpty) {
            return;
        }

        this.dt = dt;

        // 处理新进入的实体
        if (this.enteredEntities.size > 0) {
            // 优化：使用 forEach（避免迭代器开销）
            const self = this as unknown as ecs.IEntityEnterSystem;
            this.enteredEntities.forEach(entity => {
                self.entityEnter(entity);
            });
            this.enteredEntities.clear();
        }

        // 执行 firstUpdate
        const self = this as unknown as ecs.ISystemFirstUpdate;
        this.group.forEach(entity => {
            self.firstUpdate(entity);
        });

        // 切换到正常执行
        this.execute = this.tmpExecute!;
        this.execute(dt);
        this.tmpExecute = null;
    }

    /**
     * 执行模式 0：只执行 update
     * 
     * 优化：使用 forEach 代替 for-of
     * 
     * @param dt 帧时间差
     */
    private execute0(dt: number): void {
        // 优化：提前退出（但 beforeExecute 和 afterExecute 即使没有实体也要调用）
        if (this.group.isEmpty && !this.hasBeforeExecute && !this.hasAfterExecute) return;

        this.dt = dt;

        // 执行前钩子
        if (this.hasBeforeExecute) {
            const self = this as unknown as ecs.ISystemBeforeExecute;
            self.beforeExecute(dt);
        }

        // 执行 update（只有实体存在时才执行）
        if (this.hasUpdate && !this.group.isEmpty) {
            const self = this as unknown as ecs.ISystemUpdate;
            this.group.forEach(entity => {
                self.update(entity);
            });
        }

        // 执行后钩子
        if (this.hasAfterExecute) {
            const self = this as unknown as ecs.ISystemAfterExecute;
            self.afterExecute(dt);
        }
    }

    /**
     * 执行模式 1：处理实体进入/移除 + update
     * 
     * 执行顺序：entityRemove -> beforeExecute -> entityEnter -> update -> afterExecute
     * 
     * 优化：使用 forEach 代替 for-of
     * 
     * @param dt 帧时间差
     */
    private execute1(dt: number): void {
        // 处理移除的实体
        if (this.removedEntities.size > 0) {
            if (this.hasEntityRemove) {
                const self = this as unknown as ecs.IEntityRemoveSystem;
                this.removedEntities.forEach(entity => {
                    self.entityRemove(entity);
                });
            }
            this.removedEntities.clear();
        }

        // 优化：提前退出（但 beforeExecute 和 afterExecute 即使没有实体也要调用）
        const shouldContinue = !this.group.isEmpty || this.hasBeforeExecute || this.hasAfterExecute;
        if (!shouldContinue) return;

        this.dt = dt;

        // 执行前钩子
        if (this.hasBeforeExecute) {
            const self = this as unknown as ecs.ISystemBeforeExecute;
            self.beforeExecute(dt);
        }

        // 处理新进入的实体
        if (this.enteredEntities.size > 0) {
            if (this.hasEntityEnter) {
                const self = this as unknown as ecs.IEntityEnterSystem;
                this.enteredEntities.forEach(entity => {
                    self.entityEnter(entity);
                });
            }
            this.enteredEntities.clear();
        }

        // 执行 update（只有实体存在时才执行）
        if (this.hasUpdate && !this.group.isEmpty) {
            const self = this as unknown as ecs.ISystemUpdate;
            this.group.forEach(entity => {
                self.update(entity);
            });
        }

        // 执行后钩子
        if (this.hasAfterExecute) {
            const self = this as unknown as ecs.ISystemAfterExecute;
            self.afterExecute(dt);
        }
    }

    /**
     * 实体过滤规则
     * 
     * 子类必须实现此方法，返回 Matcher 来定义关心的实体
     * 
     * @returns 实体筛选器
     */
    abstract filter(): ecs.IMatcher;
}

/**
 * ECS 根系统（优化版）
 * 
 * 游戏主循环的入口，负责执行所有注册的系统
 * 
 * 优化要点：
 * 1. 使用展开操作符代替 Array.prototype.push.apply
 * 2. 缓存系统数量
 * 3. 使用传统 for 循环
 * 4. 减少属性访问次数
 */
export class ECSRootSystem {
    /** 系统执行流 */
    private readonly executeSystemFlows: ECSComblockSystem[] = [];
    
    /** 系统数量（缓存，避免每帧访问 length） */
    private systemCnt: number = 0;

    /**
     * 添加系统到执行流
     * 
     * 优化：使用展开操作符代替 Array.prototype.push.apply
     * 
     * @param system 系统或系统组合
     * @returns 当前实例（支持链式调用）
     */
    add(system: ECSSystem | ECSComblockSystem): this {
        if (system instanceof ECSSystem) {
            // 将嵌套的 System 都"摊平"，放在根 System 中进行遍历
            // 减少 execute 的频繁进入退出
            // 优化：使用展开操作符
            this.executeSystemFlows.push(...system.comblockSystems);
        } else {
            this.executeSystemFlows.push(system as ECSComblockSystem);
        }
        this.systemCnt = this.executeSystemFlows.length;
        return this;
    }

    /**
     * 初始化所有系统
     * 
     * 优化：使用传统 for 循环
     */
    init(): void {
        // 自动注册系统
        for (const sys of ECSModel.systems.values()) {
            this.add(sys as any);
        }

        // 初始化所有系统
        // 优化：传统 for 循环
        for (let i = 0; i < this.systemCnt; i++) {
            this.executeSystemFlows[i].init();
        }
    }

    /**
     * 执行所有系统（游戏主循环）
     * 
     * 优化：传统 for 循环，性能最优
     * 
     * @param dt 帧时间差（秒）
     */
    execute(dt: number): void {
        // 优化：传统 for 循环 + 缓存数组
        const systems = this.executeSystemFlows;
        const count = this.systemCnt;
        
        for (let i = 0; i < count; i++) {
            // @ts-ignore - execute 是私有方法
            systems[i].execute(dt);
        }
    }

    /**
     * 清理所有系统
     * 
     * 优化：使用传统 for 循环
     */
    clear(): void {
        // 优化：传统 for 循环
        for (let i = 0; i < this.systemCnt; i++) {
            this.executeSystemFlows[i].onDestroy();
        }
    }
    
    /**
     * 获取系统数量
     */
    get systemCount(): number {
        return this.systemCnt;
    }
    
    /**
     * 移除所有系统
     */
    removeAll(): void {
        this.clear();
        this.executeSystemFlows.length = 0;
        this.systemCnt = 0;
    }
}

/**
 * ECS 系统组合器（优化版）
 * 
 * 用于将多个相同功能模块的系统逻辑上放在一起
 * 支持系统嵌套
 * 
 * 优化要点：
 * 1. 使用展开操作符代替 Array.prototype.push.apply
 * 2. 简化添加逻辑
 */
export class ECSSystem {
    /** 组合系统列表 */
    private readonly _comblockSystems: ECSComblockSystem[] = [];
    
    /**
     * 获取组合系统列表
     */
    get comblockSystems(): ECSComblockSystem[] {
        return this._comblockSystems;
    }

    /**
     * 添加系统
     * 
     * 优化：使用展开操作符
     * 
     * @param system 系统或系统组合
     * @returns 当前实例（支持链式调用）
     */
    add(system: ECSSystem | ECSComblockSystem): this {
        if (system instanceof ECSSystem) {
            // 优化：使用展开操作符
            this._comblockSystems.push(...system._comblockSystems);
            system._comblockSystems.length = 0;
        } else {
            this._comblockSystems.push(system as ECSComblockSystem);
        }
        return this;
    }
    
    /**
     * 获取系统数量
     */
    get systemCount(): number {
        return this._comblockSystems.length;
    }
    
    /**
     * 移除所有系统
     */
    clear(): void {
        this._comblockSystems.length = 0;
    }
}